package com.unknow.first.dapp.admin.account.controller.admin;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.pagehelper.PageHelper;
import com.lianziyou.chain.common.api.CommonPage;
import com.lianziyou.chain.common.api.CommonParam;
import com.unknow.first.dapp.admin.account.constants.AccountConstants;
import com.unknow.first.dapp.admin.account.constants.AccountConstants.TradeStatus;
import com.unknow.first.dapp.admin.account.mapper.*;
import com.unknow.first.dapp.admin.account.service.*;
import com.unknow.first.dapp.admin.account.vo.QueryRechargeRecordParamVO;
import com.unknow.first.dapp.admin.account.vo.QueryWithdrawRecordParamVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.cloud.annotation.AuthLog;
import org.cloud.annotation.MfaAuth;
import org.cloud.annotation.SystemResource;
import org.cloud.constant.CoreConstant;
import org.cloud.context.RequestContextManager;
import org.cloud.entity.LoginUserDetails;
import org.cloud.exception.BusinessException;
import org.cloud.utils.CollectionUtil;
import org.cloud.utils.MyBatisPlusUtil;
import org.cloud.vo.CommonApiResult;
import org.cloud.vo.ResponseResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/admin/address/account")
@Slf4j
@SystemResource(path = "/admin/address/account")
@Api(value = "管理员：地址账户信息管理接口", tags = "管理员：地址账户信息管理接口")
public class AdminAddressAccountController {

    @Autowired
    AddressAccountInfoService addressAccountInfoService;

    @Autowired
    AddressAccountDetailService addressAccountDetailService;

    @Autowired
    private AddressCoinConfigService addressCoinConfigService;
    @Autowired
    private AddressRechargeService addressRechargeService;
    @Autowired
    private AddressWithdrawService addressWithdrawService;

    @SystemResource(value = "/accountList", description = "管理员后台查询账户列表", authMethod = CoreConstant.AuthMethod.BYUSERPERMISSION)
    @RequestMapping(method = RequestMethod.GET, value = "/accountList")
    @ApiOperation("管理员后台查询账户列表")
    public CommonApiResult<CommonPage<AddressAccountInfo>> accountList(String address, Integer coinId, Integer status,
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime, String sorts,
        CommonParam pageParam) throws BusinessException {

        QueryWrapper<AddressAccountInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(!StringUtils.isEmpty(address), AddressAccountInfo::getAddress, address)
            .eq(coinId != null, AddressAccountInfo::getCoinId, coinId).eq(status != null, AddressAccountInfo::getStatus, status)
            .ge(startTime != null, AddressAccountInfo::getCreatedDate, startTime).lt(endTime != null, AddressAccountInfo::getCreatedDate, endTime);
        PageHelper.startPage(pageParam.getPage(), pageParam.getLimit(), sorts);
        List<AddressAccountInfo> accountInfoList = addressAccountInfoService.getBaseMapper().selectList(queryWrapper);
        List<AddressCoinConfig> coinConfigList = addressCoinConfigService.getList(true);
        //根据地址查不到账户，那么就创建账户
        if (!StringUtils.isEmpty(address) && (CollectionUtils.isEmpty(accountInfoList)) || (!CollectionUtils.isEmpty(coinConfigList)
            && accountInfoList.size() < coinConfigList.size())) {
            addressAccountInfoService.createAddressAccount(address);
            //重新查
            accountInfoList = addressAccountInfoService.getBaseMapper().selectList(queryWrapper);
        }
        CommonPage<AddressAccountInfo> commonPage = CommonPage.restPage(accountInfoList);
        return CommonApiResult.createSuccessResult(commonPage);
    }

    @MfaAuth
    @AuthLog(bizType = "admin-account", desc = "管理员后台充值提现")
    @SystemResource(value = "/adminRechargeWithdraw", description = "管理员后台充值提现", authMethod = CoreConstant.AuthMethod.BYUSERPERMISSION)
    @RequestMapping(method = RequestMethod.POST, value = "/adminRechargeWithdraw")
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult adminRechargeWithdraw(@RequestBody Map<String, Object> params) throws Exception {

//        throw new BusinessException("不可用!");

        String address = params.get("address").toString();
        Integer coinId = (Integer) params.get("coinId");
        BigDecimal amount = new BigDecimal(params.get("amount").toString());
        String tradeTypeInParams = (String) params.get("tradeType");
        String adminRemark = params.get("adminRemark").toString();
        if (/*!Web3Utils.single().isETHValidAddress(address) ||*/ coinId == null || amount == null) {
            throw new BusinessException("参数非法");
        }
        AddressCoinConfig coinConfig = addressCoinConfigService.getBaseMapper().selectById(coinId);
        if (coinConfig == null || coinConfig.getStatus() == AccountConstants.CoinConfigStatus.FORBIDDEN.status) {
            throw new BusinessException("币种不存在或不可用");
        }
        AccountConstants.TradeType tradeType;
        if (tradeTypeInParams == null) {
            if (amount.compareTo(BigDecimal.ZERO) < 0) {
                tradeType = AccountConstants.TradeType.BACKGROUND_WITHDRAW;
            } else {
                tradeType = AccountConstants.TradeType.BACKGROUND_PAY;
            }
        } else {
            tradeType = AccountConstants.TradeType.valueOf(tradeTypeInParams);
        }

        String remark = null;
        if (!StringUtils.isEmpty(adminRemark)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("adminRemark", adminRemark);
            remark = jsonObject.toJSONString();
        }
        LoginUserDetails user = RequestContextManager.single().getRequestContext().getUser();
        addressAccountInfoService.processFundAndDetail(
            amount,
            coinConfig,
            tradeType,
            remark,
            0L,
            address,
            user.getUsername()
        );
         return ResponseResult.createSuccessResult();
    }

    @MfaAuth
    @AuthLog(bizType = "admin-account", desc = "管理员后台冻结解冻")
    @SystemResource(value = "/adminFreezeUnFreeze", description = "管理员后台冻结解冻", authMethod = CoreConstant.AuthMethod.BYUSERPERMISSION)
    @RequestMapping(method = RequestMethod.POST, value = "/adminFreezeUnFreeze")
    @Transactional(rollbackFor = Exception.class)
    public ResponseResult adminFreezeUnFreeze(@RequestBody Map<String, Object> params) throws Exception {

//        throw new BusinessException("不可用!");

        String address = params.get("address").toString();
        Integer coinId = (Integer) params.get("coinId");
        BigDecimal amount = new BigDecimal(params.get("amount").toString());
        String adminRemark = params.get("adminRemark").toString();
        if (/*!Web3Utils.single().isETHValidAddress(address) ||*/ coinId == null || amount == null) {
            throw new BusinessException("参数非法");
        }
        AddressCoinConfig coinConfig = addressCoinConfigService.getBaseMapper().selectById(coinId);
        if (coinConfig == null || coinConfig.getStatus() == AccountConstants.CoinConfigStatus.FORBIDDEN.status) {
            throw new BusinessException("币种不存在或不可用");
        }
        AccountConstants.TradeType tradeType;
        if (amount.compareTo(BigDecimal.ZERO) < 0) {
            tradeType = AccountConstants.TradeType.UNFREE;
        } else {
            tradeType = AccountConstants.TradeType.FREE;
        }


        String remark = null;
        if (!StringUtils.isEmpty(adminRemark)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("adminRemark", adminRemark);
            remark = jsonObject.toJSONString();
        }
        LoginUserDetails user = RequestContextManager.single().getRequestContext().getUser();
        addressAccountInfoService.processFundAndDetail(
                amount,
                coinConfig,
                tradeType,
                remark,
                0L,
                address,
                user.getUsername()
        );
        return ResponseResult.createSuccessResult();
    }

    @SystemResource(value = "/adminUpdateRechargeWithdraw", description = "管理员后台更新用户提现限额", authMethod = CoreConstant.AuthMethod.BYUSERPERMISSION)
    @RequestMapping(method = RequestMethod.POST, value = "/adminUpdateRechargeWithdraw")
    @Transactional(rollbackFor = Exception.class)
    @AuthLog(bizType = "adminUpdateWithdrawMaxAmount.withdraw", desc = "管理员后台更新用户提现限额")
    @ApiOperation("管理员后台更新用户提现限额")
    public CommonApiResult<Integer> adminUpdateRechargeWithdraw(@RequestBody Map<String, Object> params) throws BusinessException {
        Integer coinId = (Integer) params.get("coinId");
        int addressAccountId = Integer.parseInt(params.get("addressAccountId").toString());
        BigDecimal withdrawAmount = new BigDecimal(params.get("withdrawAmount").toString());

        LambdaQueryWrapper<AddressCoinConfig> addressCoinConfigQueryWrapper = Wrappers.lambdaQuery(AddressCoinConfig.class)
            .eq(AddressCoinConfig::getCoinId, coinId);

        AddressCoinConfig coinConfig = addressCoinConfigService.getBaseMapper().selectOne(addressCoinConfigQueryWrapper);
        if (coinConfig == null || coinConfig.getStatus() == AccountConstants.CoinConfigStatus.FORBIDDEN.status) {
            throw new BusinessException("币种不存在或不可用");
        }
        QueryWrapper<AddressAccountInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(AddressAccountInfo::getAddressAccountId, addressAccountId);

        AddressAccountInfo addressAccountInfo = new AddressAccountInfo();
        if (CollectionUtil.single().isNotEmpty(withdrawAmount)) {
            addressAccountInfo.setWithdrawPerDayLimit(withdrawAmount);
        }
        return CommonApiResult.createSuccessResult(addressAccountInfoService.getBaseMapper().update(addressAccountInfo, queryWrapper));
    }

    //查询资金明细
    @GetMapping("/queryAccountDetail")
    @SystemResource(value = "/queryAccountDetail", description = "查询资金明细", authMethod = CoreConstant.AuthMethod.BYUSERPERMISSION)
    @ApiOperation("查询资金明细")
    public CommonApiResult<CommonPage<AddressAccountDetail>> queryAccountDetail(CommonParam pageParam, String address, Integer coinId,
        Integer status, String remark, Integer tradeType, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime, String sorts) throws Exception {
        QueryWrapper<AddressAccountDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(!StringUtils.isEmpty(address), AddressAccountDetail::getAddress, address)
            .eq(coinId != null, AddressAccountDetail::getCoinId, coinId).eq(status != null, AddressAccountDetail::getStatus, status)
            .ge(startTime != null, AddressAccountDetail::getCreatedDate, startTime).lt(endTime != null, AddressAccountDetail::getCreatedDate, endTime)
            .eq(tradeType != null, AddressAccountDetail::getTradeType, tradeType).like(!StringUtils.isEmpty(remark), AddressAccountDetail::getRemark, remark);
        PageHelper.startPage(pageParam.getPage(), pageParam.getLimit(), sorts);

        return CommonApiResult.createSuccessResult(
            addressAccountDetailService.findListByPage(pageParam.getPage(), pageParam.getLimit(), pageParam.getSorts(), queryWrapper));
    }

    //查询资金明细
    @PostMapping("/queryAccountDetailHistory")
    @SystemResource(value = "/queryAccountDetailHistory", description = "查询历史资金明细", authMethod = CoreConstant.AuthMethod.BYUSERPERMISSION)
    @ApiOperation("查询历史资金明细")
    public CommonApiResult<CommonPage<AddressAccountDetail>> queryAccountDetailHistory(CommonParam pageParam,
        @RequestBody Map<String, Object> queryParams) throws Exception {
        PageHelper.startPage(pageParam.getPage(), pageParam.getLimit(), pageParam.getSorts());
        return CommonApiResult.createSuccessResult(
            addressAccountDetailService.findListByPageHistory(pageParam.getPage(), pageParam.getLimit(), pageParam.getSorts(), queryParams));
    }

    //查询资金明细
    @GetMapping("/queryAccountAuthWithDrawDetail")
    @SystemResource(value = "/queryAccountAuthWithDrawDetail", description = "查询资金审核记录", authMethod = CoreConstant.AuthMethod.BYUSERPERMISSION)
    @ApiOperation("查询资金审核记录")
    public CommonApiResult<CommonPage<AddressAccountDetail>> queryAccountAuthWithDrawDetail(CommonParam pageParam, String address,
        Integer coinId, String remark, Integer tradeType, @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date startTime,
        @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") Date endTime, String sorts) throws Exception {
        QueryWrapper<AddressAccountDetail> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(!StringUtils.isEmpty(address), AddressAccountDetail::getAddress, address)
            .eq(coinId != null, AddressAccountDetail::getCoinId, coinId)
            .in(AddressAccountDetail::getStatus, new Object[]{TradeStatus.AUDITING.value, TradeStatus.AUDIT_FAIL.value})
            .ge(startTime != null, AddressAccountDetail::getCreatedDate, startTime).lt(endTime != null, AddressAccountDetail::getCreatedDate, endTime)
            .eq(tradeType != null, AddressAccountDetail::getTradeType, tradeType).like(!StringUtils.isEmpty(remark), AddressAccountDetail::getRemark, remark);
        PageHelper.startPage(pageParam.getPage(), pageParam.getLimit(), sorts);
        return CommonApiResult.createSuccessResult(
            addressAccountDetailService.findListByPage(pageParam.getPage(), pageParam.getLimit(), pageParam.getSorts(), queryWrapper));
    }

    @PostMapping("/updateAccountStatus")
    @SystemResource(value = "/updateAccountStatus", description = "更新资金账户状态", authMethod = CoreConstant.AuthMethod.BYUSERPERMISSION)
    @ApiOperation("更新资金账户状态")
    public CommonApiResult<?> accountForbidden(@RequestParam Long id, @RequestParam AccountConstants.AccountStatus accountStatus){
        int updateStatusById = addressAccountInfoService.updateStatusById(id, accountStatus.status);
        Assert.isTrue(updateStatusById > 0, "修改失败");
        return CommonApiResult.createSuccessResult();
    }

    @ApiOperation("查询充值记录")
    @GetMapping("/recharge/list")
    @SystemResource(value = "/recharge/list", description = "查询充值记录", authMethod = CoreConstant.AuthMethod.BYUSERPERMISSION)
    public CommonApiResult<CommonPage<AddressRecharge>> rechargeList(CommonParam commonParam,
                                                                     QueryRechargeRecordParamVO paramVO) throws Exception {
        QueryWrapper<AddressRecharge> queryWrapper = MyBatisPlusUtil.single().getPredicate(paramVO);
        PageHelper.startPage(commonParam.getPage(), commonParam.getLimit(), ObjectUtils.isEmpty(commonParam.getSorts()) ? "id desc" : commonParam.getSorts());
        List<AddressRecharge> rechargeList = addressRechargeService.list(queryWrapper);
        CommonPage<AddressRecharge> commonPage = CommonPage.restPage(rechargeList);
        return CommonApiResult.createSuccessResult(commonPage);
    }

    @ApiOperation("查询提现记录")
    @GetMapping("/withdraw/list")
    @SystemResource(value = "/withdraw/list", description = "查询提现记录", authMethod = CoreConstant.AuthMethod.BYUSERPERMISSION)
    public CommonApiResult<CommonPage<AddressWithdraw>> withdrawList(CommonParam commonParam,
                                                                     QueryWithdrawRecordParamVO paramVO) throws Exception {
        QueryWrapper<AddressWithdraw> queryWrapper = MyBatisPlusUtil.single().getPredicate(paramVO);
        PageHelper.startPage(commonParam.getPage(), commonParam.getLimit(), ObjectUtils.isEmpty(commonParam.getSorts()) ? "id desc" : commonParam.getSorts());
        List<AddressWithdraw> rechargeList = addressWithdrawService.list(queryWrapper);
        CommonPage<AddressWithdraw> commonPage = CommonPage.restPage(rechargeList);
        return CommonApiResult.createSuccessResult(commonPage);
    }


}
